package com.easysoft.commons.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.*;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Http请求工具类(支持Https)
 * 
 * @author try
 */
public class HttpClient {

	private static final Logger logger = LoggerFactory.getLogger(HttpURLConnection.class);

	private static final String ACCEPT_CHARSET = "UTF-8";
	private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36";// 模拟浏览器
	private static final int TIME_OUT = 50000;

	private enum Method {
		POST, GET
	}

	private static String proxyOn = null;
	private static String proxyHost = null;
	private static int proxyPort = 80;

	static {
		proxyOn = PropertyConfig.getProperty("http.proxyOn");
		proxyHost = PropertyConfig.getProperty("http.proxyHost");
		proxyPort = StringUtils.toInt(PropertyConfig.getProperty("http.proxyPort"), 80);
	}

	public static String get(String urlPath) throws Exception {

		URL url = new URL(urlPath);

		HttpURLConnection connection = newConnection(url, Method.GET);

		return readResponse(connection);
	}

	public static String post(String urlPath) throws Exception {
		return post(urlPath, null);
	}

	public static String post(final String urlPath, final Map<String, String> parameters) throws Exception {

		// 迭代处理参数
		StringBuffer parameterBuffer = new StringBuffer();

		if (parameters != null) {
			Set<Map.Entry<String, String>> set = parameters.entrySet();
			Iterator<Map.Entry<String, String>> it = set.iterator();

			Map.Entry<String, String> item = null;
			String key = null;
			String value = null;

			while (it.hasNext()) {
				item = it.next();
				key = item.getKey();
				value = item.getValue();

				if (key != null && value != null) {
					parameterBuffer.append(key).append("=").append(URLEncoder.encode(value, "UTF-8"));
					if (it.hasNext()) {
						parameterBuffer.append("&");
					}
				}
			}
		}

		logger.debug("POST parameter : {}", parameterBuffer.toString());

		URL url = new URL(urlPath);

		HttpURLConnection connection = newConnection(url, Method.POST);
		connection.setRequestProperty("Content-Length", String.valueOf(parameterBuffer.length()));

		OutputStream outputStream = connection.getOutputStream();
		OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
		outputStreamWriter.write(parameterBuffer.toString());
		outputStreamWriter.flush();

		return readResponse(connection);
	}

	private static HttpURLConnection newConnection(URL url, Method method) throws IOException {

		HttpURLConnection conn = null;

		if (proxyOn != null && proxyOn.equalsIgnoreCase("on")) {
			Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
			conn = (HttpURLConnection) url.openConnection(proxy);
		}
		else {
			conn = (HttpURLConnection) url.openConnection();
		}

		conn.setConnectTimeout(TIME_OUT);// 连接超时
		conn.setReadTimeout(TIME_OUT);// 读取超时
		conn.setRequestProperty("Accept", "*/*");// 返回接收类型
		conn.setRequestProperty("Accept-Charset", ACCEPT_CHARSET);
		conn.setRequestProperty("Connection", "keep-alive");// 请求连接方式(连接一会)
		conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");// 提交信息将url编码
		conn.setRequestProperty("User-agent", USER_AGENT);// 请求客户端信息
		conn.setInstanceFollowRedirects(false);

		if (method == Method.POST) {
			conn.setRequestMethod("POST");// 请求方式(GET,POST)
			conn.setDoOutput(true);// 允许输出流
			conn.setDoInput(true); // 允许输入流
			conn.setUseCaches(false);// 禁用缓存
			conn.setInstanceFollowRedirects(true); // 允许重定向
		}

		return conn;
	}

	private static String readResponse(HttpURLConnection conn) throws Exception {

		int responseCode = conn.getResponseCode();

		if (responseCode != HttpURLConnection.HTTP_OK) {
			logger.error("code:{}, result : {}", responseCode, conn.getResponseMessage());
			throw new Exception("HTTP Request is not success, Response code is " + conn.getResponseCode());
		}

		StringBuffer resultBuffer = new StringBuffer();

		InputStream is = null;
		InputStreamReader sr = null;
		BufferedReader br = null;
		String tempLine = null;

		try {
			is = conn.getInputStream();
			sr = new InputStreamReader(is, ACCEPT_CHARSET);
			br = new BufferedReader(sr);
			while ((tempLine = br.readLine()) != null) {
				resultBuffer.append(tempLine);
			}
		}
		finally {
			try {
				conn.disconnect();

				if (br != null) {
					br.close();
				}

				if (sr != null) {
					sr.close();
				}

				if (is != null) {
					is.close();
				}
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}

		String result = resultBuffer.toString();

		logger.debug("Result : {}", result);

		return result;
	}
}
